home *** CD-ROM | disk | FTP | other *** search
- /* $Header: ntp_util.c,v 1.3 91/06/19 11:08:09 ath Exp $ */
- /*
- * ntp_util.c - stuff I didn't have any other place for
- */
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
-
- #include "global.h"
- #include "sockaddr.h"
- #include "mbuf.h" /* for {get,put}{16,32} */
- #include "netuser.h"
-
- #include "ntp_types.h"
- #include "ntp_syslog.h"
- #include "ntp_fp.h"
- #include "ntp.h"
- #include "ntp_calendar.h"
-
- /*
- * This contains odds and ends. Right now the only thing you'll find
- * in here is the hourly stats printer and some code to support rereading
- * the keys file, but I may eventually put other things in here such as
- * code to do something with the leap bits.
- */
-
- #ifdef XNTP_AUTHENTICATE
- /*
- * Name of the keys file
- */
- char *key_file_name;
- #endif /* XNTP_AUTHENTICATE */
-
- #if 0 /* No drift file right now */
- /*
- * The name of the drift_comp file and the temporary.
- */
- char *stats_drift_file;
- char *stats_temp_file;
- #endif /* 0 */
-
- /*
- * We query the errno to see what kind of error occured
- * when opening the drift file.
- */
- extern int errno;
-
- #ifdef DEBUG
- extern int debug;
- #endif
-
- /*
- * init_util - initialize the utilities
- */
- void
- init_util()
- {
- #if 0
- stats_drift_file = 0;
- stats_temp_file = 0;
- #endif /* 0 */
- #ifdef XNTP_AUTHENTICATE
- key_file_name = 0;
- #endif
- }
-
-
- /*
- * hourly_stats - print some interesting stats
- */
- void
- hourly_stats()
- {
- int fd;
- char *val;
- int vallen;
- extern l_fp drift_comp;
- extern long compliance;
- extern char *lfptoa();
- extern char *mfptoa();
-
- syslog(LOG_INFO, "hourly check: drift %s compliance %s",
- lfptoa(&drift_comp, 8),
- mfptoa((compliance<0)?(-1L):0L, compliance, 8));
-
-
- #if 0 /* no drift file for now in NOS */
- if (stats_drift_file != 0) {
- fd = open(stats_temp_file, O_WRONLY|O_TRUNC|O_CREAT, 0666);
- if (fd == -1) {
- syslog(LOG_ERR, "can't open %s: %m", stats_temp_file);
- return;
- }
-
- val = lfptoa(&drift_comp, 9);
- vallen = strlen(val);
- /*
- * Hack here. Turn the trailing \0 into a \n and write it.
- */
- val[vallen] = '\n';
- if (write(fd, val, vallen+1) == -1) {
- syslog(LOG_ERR, "write to %s failed: %m",
- stats_temp_file);
- (void) close(fd);
- (void) unlink(stats_temp_file);
- } else {
- (void) close(fd);
- /* atomic */
- (void) rename(stats_temp_file, stats_drift_file);
- }
- }
- #endif /* 0 */
- }
-
-
- /*
- * stats_config - configure the stats operation
- */
- void
- stats_config(item, value)
- int item;
- char *value; /* only one type so far */
- {
- register char *cp;
- FILE *fp;
- int len;
- /* char buf[128]; */
- l_fp old_drift;
- extern void loop_config();
- extern char *lfptoa();
-
- switch(item) {
- #if 0 /* no drift file yet. */
- case STATS_FREQ_FILE:
- if (stats_drift_file != 0) {
- (void) free(stats_drift_file);
- (void) free(stats_temp_file);
- stats_drift_file = 0;
- stats_temp_file = 0;
- }
-
- if (value == 0 || (len = strlen(value)) == 0)
- break;
-
- stats_drift_file = emalloc((u_int)(len + 1));
- stats_temp_file = emalloc((u_int)(len + sizeof(".TEMP")));
- bcopy(value, stats_drift_file, len+1);
- bcopy(value, stats_temp_file, len);
- bcopy(".TEMP", stats_temp_file + len, sizeof(".TEMP"));
- #ifdef DEBUG
- if (debug > 1) {
- printf("stats drift file %s\n", stats_drift_file);
- printf("stats temp file %s\n", stats_temp_file);
- }
- #endif
-
- if ((fp = fopen(stats_drift_file, "r")) == NULL) {
- if (errno != ENOENT)
- syslog(LOG_ERR, "can't open %s: %m",
- stats_drift_file);
- break;
- }
-
- if (fgets(buf, sizeof buf, fp) == NULL) {
- syslog(LOG_ERR, "can't read %s: %m",
- stats_drift_file);
- (void) fclose(fp);
- break;
- }
-
- (void) fclose(fp);
-
- /*
- * We allow leading spaces, then the number. Terminate
- * at any trailing space or string terminator.
- */
- cp = buf;
- while (isspace(*cp))
- cp++;
- while (*cp != '\0' && !isspace(*cp))
- cp++;
- *cp = '\0';
-
- if (!atolfp(buf, &old_drift)) {
- syslog(LOG_ERR, "drift value %s invalid", buf);
- break;
- }
-
- /*
- * Finally! Give value to the loop filter.
- */
- #ifdef DEBUG
- if (debug > 1) {
- printf("loop_config finds old drift of %s\n",
- lfptoa(&old_drift, 9));
- }
- #endif
- loop_config(LOOP_DRIFTCOMP, &old_drift);
- break;
- #endif /* 0 */
-
- /* The drift value itself is passed in. */
- case STATS_FREQ:
- if (!atolfp(value, &old_drift)) {
- tprintf("drift value %s invalid", value);
- break;
- }
-
- loop_config(LOOP_DRIFTCOMP, &old_drift);
- break;
-
- default:
- /* oh well */
- break;
- }
- }
-
-
- #ifdef XNTP_AUTHENTICATE
-
- /*
- * getauthkeys - read the authentication keys from the specified file
- */
- void
- getauthkeys(keyfile)
- char *keyfile;
- {
- int len;
-
- len = strlen(keyfile);
- if (len == 0)
- return;
-
- if (key_file_name != 0) {
- if (len > strlen(key_file_name)) {
- (void) free(key_file_name);
- key_file_name = 0;
- }
- }
-
- if (key_file_name == 0)
- key_file_name = mallocw((u_int)(len + 1));
-
- bcopy(keyfile, key_file_name, len+1);
-
- authreadkeys(key_file_name);
- }
-
-
- /*
- * rereadkeys - read the authentication key file over again.
- */
- void
- rereadkeys()
- {
- if (key_file_name != 0)
- authreadkeys(key_file_name);
- }
-
- #endif /* XNTP_AUTHENTICATE */
-
-
- /* htons and friends, implemented using the equivalent NOS functions. */
- int16
- htons (h)
- int16 h;
- {
- int16 n;
- put16 ((char *)&n, h);
- return n;
- }
-
- int16
- ntohs (n)
- int16 n;
- {
- return get16 ((char *)&n);
- }
-
- int32
- htonl (h)
- int32 h;
- {
- int32 n;
- put32 ((char *)&n, h);
- return n;
- }
-
- int32
- ntohl (n)
- int32 n;
- {
- return get32 ((char *)&n);
- }
-
-
- /*
- * And here we have all the routines used by the NOS ntp code from xntp's
- * library. I didn't want to make yet another library for NOS.
- */
-
- /******
- * ranny.c
- */
-
- /*
- * Random number generator is:
- *
- * Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
- * This will be free software, but only when it is finished.
- *
- * Used in xntp by permission of the author. If copyright is
- * annoying to you, read no further. Instead, look up the reference,
- * write me an equivalent to this and send it back to me.
- */
-
- /*
- * Random number generator; see Knuth Vol 2. 2nd ed. p.27 (section 3.2.2)
- */
-
- /*
- * 55 random numbers, not all even. Note we don't initialize ran_y
- * directly since I have had thoughts of putting this in an EPROM
- */
- static u_long ran_y[55];
-
- static u_long init_ran_y[55] = {
- 1860909544, 231033423, 437666411, 1349655137, 2014584962,
- 504613712, 656256107, 1246027206, 573713775, 643466871,
- 540235388, 1630565153, 443649364, 729302839, 1933991552,
- 944681982, 949111118, 406212522, 1065063137, 1712954727,
- 73280612, 787623973, 1874130997, 801658492, 73395958,
- 739165367, 596047144, 490055249, 1131094323, 662727104,
- 483614097, 844520219, 893760527, 921280508, 46691708,
- 760861842, 1425894220, 702947816, 2006889048, 1999607995,
- 1346414687, 399640789, 1482689501, 1790064052, 1128943628,
- 1269197405, 587262386, 2078054746, 1675409928, 1652325524,
- 1643525825, 1748690540, 292465849, 1370173174, 402865384
- };
-
- static int ran_j;
- static int ran_k;
-
-
- /*
- * ranp2 - return a random integer in the range 0 .. (1<<m)-1
- */
- u_long
- ranp2(m)
- int m;
- {
- u_long r;
-
- ran_y[ran_k] += ran_y[ran_j]; /* overflow does a mod */
- r = ran_y[ran_k];
- if (ran_k-- == 0) ran_k = 54;
- if (ran_j-- == 0) ran_j = 54;
- return (r & ((1<<m)-1));
- }
-
- #ifdef notdef
- /*
- * ranny - return a random integer in the range 0 .. m-1
- */
- u_long
- ranny(m)
- u_int m;
- {
- unsigned long r;
-
- ran_y[ran_k] += ran_y[ran_j]; /* overflow does a mod */
- r = ran_y[ran_k];
- if (ran_k-- == 0) ran_k = 54;
- if (ran_j-- == 0) ran_j = 54;
- return (r % m);
- }
- #endif /* notdef */
-
- /*
- * init_random - do initialization of random number routine
- */
- void
- init_random()
- {
- register int i;
- register time_t now;
-
- ran_j = 23;
- ran_k = 54;
-
- /*
- * Randomize the seed array some more. The time of day
- * should be initialized by now.
- */
- now = (time_t)(time((time_t *)0))|01;
-
- for (i = 0; i < 55; ++i)
- ran_y[i] = now * init_ran_y[i]; /* overflow does a mod */
- }
-
- /* ntp passes ntoa a pointer to a sockaddr_in, and wants a char * back.
- * NOS has inet_ntoa() which takes a long (in host byte order) and returns a
- * char *.
- */
- char *
- ntoa(addr)
- struct sockaddr_in *addr;
- {
- return inet_ntoa (ntohl (addr->sin_addr.s_addr));
- }
-
- /*
- * lib_strbuf.h - definitions for routines which use the common string buffers
- */
-
- /*
- * Sizes of things
- */
- #define LIB_NUMBUFS 5
- #define LIB_BUFLENGTH 80
-
- /*
- * Macro to get a pointer to the next buffer
- */
- #define LIB_GETBUF(buf) \
- do { \
- buf = &lib_stringbuf[lib_nextbuf][0]; \
- if (++lib_nextbuf >= LIB_NUMBUFS) \
- lib_nextbuf = 0; \
- } while (0)
-
-
- /*
- * lib_strbuf - library string storage
- */
-
- /*
- * Storage declarations
- */
- char lib_stringbuf[LIB_NUMBUFS][LIB_BUFLENGTH];
- int lib_nextbuf;
-
- /*
- * initialization routine. Might be needed if the code is ROMized.
- */
- void
- init_lib()
- {
- lib_nextbuf = 0;
- }
-
-
- /*
- * lfptoa - return an asciized representation of a signed l_fp number
- */
-
- char *
- lfptoa(fpv, ndec)
- l_fp *fpv;
- int ndec;
- {
- extern char *mfptoa();
-
- return mfptoa(fpv->l_ui, fpv->l_uf, ndec);
- }
-
- /*
- * atolfp - convert an ascii string to an l_fp number
- */
-
- /*
- * Powers of 10
- */
- static u_long ten_to_the_n[10] = {
- 0,
- 10,
- 100,
- 1000,
- 10000,
- 100000,
- 1000000,
- 10000000,
- 100000000,
- 1000000000,
- };
-
-
- int
- atolfp(str, lfp)
- char *str;
- l_fp *lfp;
- {
- register char *cp;
- register u_long dec_i;
- register u_long dec_f;
- char *ind;
- int ndec;
- int isneg;
- static char *digits = "0123456789";
-
- isneg = 0;
- dec_i = dec_f = 0;
- ndec = 0;
- cp = str;
-
- /*
- * We understand numbers of the form:
- *
- * [spaces][-][digits][.][digits][spaces|\n|\0]
- */
- while (isspace(*cp))
- cp++;
-
- if (*cp == '-') {
- cp++;
- isneg = 1;
- }
-
- /* gdt */
- if (*cp == '+') {
- cp++;
- isneg = 0;
- }
-
- if (*cp != '.' && !isdigit(*cp))
- return 0;
-
- #define index strchr /* ANSI C */
- while (*cp != '\0' && (ind = index(digits, *cp)) != NULL) {
- dec_i = (dec_i << 3) + (dec_i << 1); /* multiply by 10 */
- dec_i += (ind - digits);
- cp++;
- }
-
- if (*cp != '\0' && !isspace(*cp)) {
- if (*cp++ != '.')
- return 0;
-
- while (ndec < 9 && *cp != '\0'
- && (ind = index(digits, *cp)) != NULL) {
- ndec++;
- dec_f = (dec_f << 3) + (dec_f << 1); /* *10 */
- dec_f += (ind - digits);
- cp++;
- }
-
- while (isdigit(*cp))
- cp++;
-
- if (*cp != '\0' && !isspace(*cp))
- return 0;
- }
-
- if (ndec > 0) {
- register u_long tmp;
- register u_long bit;
- register u_long ten_fact;
-
- ten_fact = ten_to_the_n[ndec];
-
- tmp = 0;
- bit = 0x80000000;
- while (bit != 0) {
- dec_f <<= 1;
- if (dec_f >= ten_fact) {
- tmp |= bit;
- dec_f -= ten_fact;
- }
- bit >>= 1;
- }
- if ((dec_f << 1) > ten_fact)
- tmp++;
- dec_f = tmp;
- }
-
- if (isneg)
- M_NEG(dec_i, dec_f);
-
- lfp->l_ui = dec_i;
- lfp->l_uf = dec_f;
- return 1;
- }
-
-
- /*
- * umfptoa - Return an asciized representation of an unsigned long fp number
- */
- char *
- umfptoa(fpi, fpf, ndec)
- u_long fpi;
- u_long fpf;
- int ndec;
- {
- extern char *dolfptoa();
-
- return dolfptoa(fpi, fpf, 0, ndec, 0);
- }
-
- /*
- * mfptoa - Return an asciized representation of a signed long fp number
- */
- char *
- mfptoa(fpi, fpf, ndec)
- u_long fpi;
- u_long fpf;
- int ndec;
- {
- int isneg;
- extern char *dolfptoa();
-
- if (M_ISNEG(fpi, fpf)) {
- isneg = 1;
- M_NEG(fpi, fpf);
- } else
- isneg = 0;
-
- return dolfptoa(fpi, fpf, isneg, ndec, 0);
- }
-
- /*
- * fptoa - return an asciized representation of an s_fp number
- */
- char *
- fptoa(fpv, ndec)
- s_fp fpv;
- int ndec;
- {
- u_fp plusfp;
- int neg;
- extern char *dofptoa();
-
- if (fpv < 0) {
- plusfp = (u_fp)(-fpv);
- neg = 1;
- } else {
- plusfp = (u_fp)fpv;
- neg = 0;
- }
-
- return dofptoa(plusfp, neg, ndec, 0);
- }
-
- /*
- * ufptoa - return an asciized representation of an u_fp number
- */
-
- char *
- ufptoa(fpv, ndec)
- u_fp fpv;
- int ndec;
- {
- extern char *dofptoa();
-
- return dofptoa(fpv, 0, ndec, 0);
- }
-
-
- /*
- * ufptoms - return an asciized u_fp number in milliseconds
- */
- char *
- ufptoms(fpv, ndec)
- u_fp fpv;
- int ndec;
- {
- extern char *dofptoa();
-
- return dofptoa(fpv, 0, ndec, 1);
- }
-
-
- /*
- * ulfptoms - return an asciized unsigned l_fp number in milliseconds
- */
- char *
- ulfptoms(fpv, ndec)
- l_fp *fpv;
- int ndec;
- {
- extern char *umfptoms();
-
- return umfptoms(fpv->l_ui, fpv->l_uf, ndec);
- }
-
- /*
- * lfptoms - return an asciized signed l_fp number in milliseconds
- */
- char *
- lfptoms(fpv, ndec)
- l_fp *fpv;
- int ndec;
- {
- extern char *mfptoms();
-
- return mfptoms(fpv->l_ui, fpv->l_uf, ndec);
- }
-
- /*
- * fptoms - return an asciized s_fp number in milliseconds
- */
- char *
- fptoms(fpv, ndec)
- s_fp fpv;
- int ndec;
- {
- u_fp plusfp;
- int neg;
- extern char *dofptoa();
-
- if (fpv < 0) {
- plusfp = (u_fp)(-fpv);
- neg = 1;
- } else {
- plusfp = (u_fp)fpv;
- neg = 0;
- }
-
- return dofptoa(plusfp, neg, ndec, 1);
- }
-
-
- /*
- * numtoa - return asciized network numbers store in local array space
- */
- char *
- numtoa(num)
- u_long num;
- {
- register u_long netnum;
- register char *buf;
-
- netnum = ntohl(num);
- LIB_GETBUF(buf);
-
- (void) sprintf(buf, "%d.%d.%d.%d", (int)((netnum>>24)&0xff),
- (int)((netnum>>16)&0xff), (int)((netnum>>8)&0xff),
- (int)(netnum&0xff));
-
- return buf;
- }
-
-
- /*
- * atoint - convert an ascii string to a signed long, with error checking
- */
- int
- atoint(str, ival)
- char *str;
- long *ival;
- {
- register u_long u;
- register char *cp;
- register int isneg;
- register int oflow_digit;
-
- cp = str;
-
- if (*cp == '-') {
- cp++;
- isneg = 1;
- oflow_digit = '8';
- } else {
- isneg = 0;
- oflow_digit = '7';
- }
-
- if (*cp == '\0')
- return 0;
-
- u = 0;
- while (*cp != '\0') {
- if (!isdigit(*cp))
- return 0;
- if (u > 214748364 || (u == 214748364 && *cp > oflow_digit))
- return 0; /* overflow */
- u = (u << 3) + (u << 1);
- u += *cp++ - '0'; /* ascii dependent */
- }
-
- if (isneg)
- *ival = -((long)u);
- else
- *ival = (long)u;
- return 1;
- }
-
-
- /*
- * mfptoms - Return an asciized signed long fp number in milliseconds
- */
- char *
- mfptoms(fpi, fpf, ndec)
- u_long fpi;
- u_long fpf;
- int ndec;
- {
- int isneg;
- extern char *dolfptoa();
-
- if (M_ISNEG(fpi, fpf)) {
- isneg = 1;
- M_NEG(fpi, fpf);
- } else
- isneg = 0;
-
- return dolfptoa(fpi, fpf, isneg, ndec, 1);
- }
-
- /*
- * umfptoms - Return an asciized unsigned long fp number in milliseconds
- */
- char *
- umfptoms(fpi, fpf, ndec)
- u_long fpi;
- u_long fpf;
- int ndec;
- {
- extern char *dolfptoa();
-
- return dolfptoa(fpi, fpf, 0, ndec, 1);
- }
-
- /*
- * dolfptoa - do the grunge work of converting an l_fp number to decimal
- */
- char *
- dolfptoa(fpi, fpv, neg, ndec, msec)
- u_long fpi;
- u_long fpv;
- int neg;
- int ndec;
- int msec;
- {
- register u_char *cp, *cpend;
- register u_long work_i;
- register int dec;
- u_char cbuf[24];
- u_char *cpdec;
- char *buf;
- char *bp;
-
- /*
- * Get a string buffer before starting
- */
- LIB_GETBUF(buf);
-
- /*
- * Zero the character buffer
- */
- bzero(cbuf, sizeof(cbuf));
-
- /*
- * Work on the integral part. This is biased by what I know
- * compiles fairly well for a 68000.
- */
- cp = cpend = &cbuf[10];
- work_i = fpi;
- if (work_i & 0xffff0000) {
- register u_long lten = 10;
- register u_long ltmp;
-
- do {
- ltmp = work_i;
- work_i /= lten;
- ltmp -= (work_i<<3) + (work_i<<1);
- *--cp = (u_char)ltmp;
- } while (work_i & 0xffff0000);
- }
- if (work_i != 0) {
- register u_short sten = 10;
- register u_short stmp;
- register u_short swork = (u_short)work_i;
-
- do {
- stmp = swork;
- swork /= sten;
- stmp -= (swork<<3) + (swork<<1);
- *--cp = (u_char)stmp;
- } while (swork != 0);
- }
-
- /*
- * Done that, now deal with the problem of the fraction. First
- * determine the number of decimal places.
- */
- if (msec) {
- dec = ndec + 3;
- if (dec < 3)
- dec = 3;
- cpdec = &cbuf[13];
- } else {
- dec = ndec;
- if (dec < 0)
- dec = 0;
- cpdec = &cbuf[10];
- }
- if (dec > 12)
- dec = 12;
-
- /*
- * If there's a fraction to deal with, do so.
- */
- if (fpv != 0) {
- register u_long work_f;
-
- work_f = fpv;
- while (dec > 0) {
- register u_long tmp_i;
- register u_long tmp_f;
-
- dec--;
- /*
- * The scheme here is to multiply the
- * fraction (0.1234...) by ten. This moves
- * a junk of BCD into the units part.
- * record that and iterate.
- */
- work_i = 0;
- M_LSHIFT(work_i, work_f);
- tmp_i = work_i;
- tmp_f = work_f;
- M_LSHIFT(work_i, work_f);
- M_LSHIFT(work_i, work_f);
- M_ADD(work_i, work_f, tmp_i, tmp_f);
- *cpend++ = (u_char)work_i;
- if (work_f == 0)
- break;
- }
-
- /*
- * Rounding is rotten
- */
- if (work_f & 0x80000000) {
- register u_char *tp = cpend;
-
- *(--tp) += 1;
- while (*tp >= 10) {
- *tp = 0;
- *(--tp) += 1;
- };
- if (tp < cp)
- cp = tp;
- }
- }
- cpend += dec;
-
-
- /*
- * We've now got the fraction in cbuf[], with cp pointing at
- * the first character, cpend pointing past the last, and
- * cpdec pointing at the first character past the decimal.
- * Remove leading zeros, then format the number into the
- * buffer.
- */
- while (cp < cpdec) {
- if (*cp != 0)
- break;
- cp++;
- }
- if (cp == cpdec)
- --cp;
-
- bp = buf;
- if (neg)
- *bp++ = '-';
- while (cp < cpend) {
- if (cp == cpdec)
- *bp++ = '.';
- *bp++ = (char)(*cp++ + '0'); /* ascii dependent? */
- }
- *bp = '\0';
-
- /*
- * Done!
- */
- return buf;
- }
-
-
- /*
- * dofptoa - do the grunge work to convert an fp number to ascii
- */
- char *
- dofptoa(fpv, neg, ndec, msec)
- u_fp fpv;
- int neg;
- int ndec;
- int msec;
- {
- register u_char *cp, *cpend;
- register u_long val;
- register short dec;
- u_char cbuf[12];
- u_char *cpdec;
- char *buf;
- char *bp;
-
- /*
- * Get a string buffer before starting
- */
- LIB_GETBUF(buf);
-
- /*
- * Zero out the buffer
- */
- bzero((char *)cbuf, sizeof cbuf);
-
- /*
- * Set the pointers to point at the first
- * decimal place. Get a local copy of the value.
- */
- cp = cpend = &cbuf[5];
- val = fpv;
-
- /*
- * If we have to, decode the integral part
- */
- if (!(val & 0xffff0000))
- cp--;
- else {
- register u_short sv = (u_short)(val >> 16);
- register u_short tmp;
- register u_short ten = 10;
-
- do {
- tmp = sv;
- sv /= ten;
- *(--cp) = tmp - ((sv<<3) + (sv<<1));
- } while (sv != 0);
- }
-
- /*
- * Figure out how much of the fraction to do
- */
- if (msec) {
- dec = ndec + 3;
- if (dec < 3)
- dec = 3;
- cpdec = &cbuf[8];
- } else {
- dec = ndec;
- cpdec = cpend;
- }
-
- if (dec > 6)
- dec = 6;
-
- if (dec > 0) {
- do {
- val &= 0xffff;
- val = (val << 3) + (val << 1);
- *cpend++ = (u_char)(val >> 16);
- } while (--dec > 0);
- }
-
- if (val & 0x8000) {
- register u_char *tp;
- /*
- * Round it. Ick.
- */
- tp = cpend;
- *(--tp) += 1;
- while (*tp >= 10) {
- *tp = 0;
- *(--tp) += 1;
- }
- }
-
- /*
- * Remove leading zeroes if necessary
- */
- while (cp < (cpdec -1) && *cp == 0)
- cp++;
-
- /*
- * Copy it into the buffer, asciizing as we go.
- */
- bp = buf;
- if (neg)
- *bp++ = '-';
-
- while (cp < cpend) {
- if (cp == cpdec)
- *bp++ = '.';
- *bp++ = (char)(*cp++ + '0');
- }
- *bp = '\0';
- return buf;
- }
-
-
- /*
- * calleapwhen - determine the number of seconds to the next possible
- * leap occurance and the last one.
- */
-
- /*
- * calleaptab - leaps occur at the end of December and June
- */
- static long calleaptab[10] = {
- -(JAN+FEBLEAP)*SECSPERDAY, /* leap previous to cycle */
- (MAR+APR+MAY+JUN)*SECSPERDAY, /* end of June */
- (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY, /* end of Dec */
- (MAR+APR+MAY+JUN)*SECSPERDAY + SECSPERYEAR,
- (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + SECSPERYEAR,
- (MAR+APR+MAY+JUN)*SECSPERDAY + 2*SECSPERYEAR,
- (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + 2*SECSPERYEAR,
- (MAR+APR+MAY+JUN)*SECSPERDAY + 3*SECSPERYEAR,
- (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + 3*SECSPERYEAR,
- (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC+JAN+FEBLEAP+MAR+APR+MAY+JUN)
- *SECSPERDAY + 3*SECSPERYEAR, /* next after current cycle */
- };
-
- void
- calleapwhen(ntpdate, leaplast, leapnext)
- u_long ntpdate;
- u_long *leaplast;
- u_long *leapnext;
- {
- register u_long dateincycle;
- register int i;
-
- /*
- * Find the offset from the start of the cycle
- */
- dateincycle = ntpdate;
- if (dateincycle >= MAR1988)
- dateincycle -= MAR1988;
- else
- dateincycle -= MAR1900;
-
- while (dateincycle >= SECSPERCYCLE)
- dateincycle -= SECSPERCYCLE;
-
- /*
- * Find where we are with respect to the leap events.
- */
- for (i = 1; i < 9; i++)
- if (dateincycle < (u_long)calleaptab[i])
- break;
-
- /*
- * i points at the next leap. Compute the last and the next.
- */
- *leaplast = (u_long)((long)dateincycle - calleaptab[i-1]);
- *leapnext = (u_long)(calleaptab[i] - (long)dateincycle);
- }
-